 var express = require('express');
 var bodyParser = require('body-parser');
 var fs = require('fs');
 var https = require('https');
 var http = require('http');
 var format = require('string-format');
 format.extend(String.prototype);

 class TWebSvr {
     constructor() {
         this.objs = {
             app: null,
             server: null
         };
         this.config = {
             port: 20039,
             domain: "wss.hhdata.cn",
             https: {
                 enable: true,
                 keyFn: "D:/gitee/hhudev/svr/keys/5919249_wss.hhdata.cn.key",
                 certFn: "D:/gitee/hhudev/svr/keys/5919249_wss.hhdata.cn.pem"
             },
             statics: {
                 "/": "D:/gitee/hhudev/web"
             }
         };
         this.statics = {
             "/": "D:/gitee/hhudev/web"
         };
         this.routes = {
             common: {
                 default: {
                     hello: function(result, request, response) {
                         if (!result) {
                             result = {
                                 error: null,
                                 data: ""
                             };
                         }
                         result.data = "hello . hhu dev.";
                         response.send(JSON.stringify(result));
                     },
                     errHandler: function(result, request, response) {
                         if (!result || result == null) {
                             result = {};
                         }
                         result.error = "api path is error.";
                         response.send(JSON.stringify(result));
                     }
                 }
             }
         }
     }
     registRoute(appId, module, action, handler) {
         if (!this.routes[appId]) {
             this.routes[appId] = {}
         }
         if (!this.routes[appId][module]) {
             this.routes[appId][module] = {}
         }
         this.routes[appId][module][action] = handler;
     }
     getHandler(appId, module, action) {
         var me = this;
         var handler = me.routes.common.default.errHandler;
         if (me.routes[appId] &&
             me.routes[appId][module] &&
             me.routes[appId][module][action]) {
             handler = me.routes[appId][module][action];
         }
         return handler;
     }
     start(callback) {
         var me = this;
         return new Promise((success, faild) => {
             try {
                 var app = express();
                 /*
                  * 静态虚拟目录
                  * */
                 for (var sp in me.statics) {
                     //var webPath = me.statics[sp];
                     var webPath = me.config.statics[sp];
                     app.use(sp, express.static(webPath));
                 }
                 /*
                  * 动态路由
                  * */
                 var urlencodedParser = bodyParser.urlencoded({ extended: false });
                 app.use(urlencodedParser);
                 app.use(bodyParser.json());
                 var jsonParser = bodyParser.json();
                 var apiPath = "/:appId/:module/:action";
                 app.all(apiPath, jsonParser, function(req, res) {
                     try {
                         var appId = req.params.appId;
                         var module = req.params.module;
                         var action = req.params.action;
                         var handler = me.getHandler(appId, module, action);

                         res.header("Access-Control-Allow-Origin", "*");
                         res.header("Access-Control-Allow-Headers", "*");
                         res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");
                         var ps = req.query;
                         if (!ps || ps == null) {
                             ps = {}
                         }
                         var result = {
                             appId: appId,
                             module: module,
                             action: action,
                             ps: ps,
                             error: null,
                             result: null
                         };

                         var extend = function(a, b) {
                             var res = {};
                             if (a && a != null) {
                                 Object.keys(a).forEach(k => {
                                     res[k] = a[k];
                                 })
                             }
                             if (b && b != null) {
                                 Object.keys(b).forEach(k => {
                                     res[k] = b[k];
                                 })
                             }
                             return res;
                         }


                         if (req.method == "POST") {
                             if (req.headers && req.headers["content-type"] && req.headers["content-type"].indexOf('application/json') >= 0) {

                                 if (req.body) {
                                     Object.keys(req.body).forEach(k => {
                                         result.ps[k] = req.body[k];
                                     })
                                 }
                                 handler(result, req, res);
                             } else {
                                 req.setEncoding('utf8');
                                 req.on('data', function(data) {
                                     try {
                                         var obj = JSON.parse(data);
                                         ps = extend(ps, obj);
                                     } catch (ee) {
                                         console.log(ee)
                                     }
                                 });
                                 req.on('end', function() {
                                     handler(result, req, res);
                                 });
                             }
                         } else if (req.method == "GET") {
                             handler(result, req, res);
                         } else if (req.method == "OPTIONS") {
                             res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Access-Control-Allow-Headers,Authorization,X-Requested-With');
                             res.header("Access-Control-Allow-Origin", "*");
                             res.header("Access-Control-Allow-Headers", "*");
                             res.send(200);
                         }
                     } catch (erHandler) {
                         console.log(erHandler);
                         res.send(400);
                     }
                 });

                 var options = {};
                 try {
                     if (me.config.https.enable) {
                         options = {
                             key: fs.readFileSync(me.config.https.keyFn),
                             cert: fs.readFileSync(me.config.https.certFn)
                         };
                     }
                 } catch (eer) {
                     console.log(eer);
                 }

                 var webServer = me.config.https.enable ? https.createServer(options, app) : http.createServer(options, app);

                 webServer.listen(me.config.port, function(err) {
                     if (err) {
                         console.log('start web error.', err);
                     } else {
                         me.objs.app = app;
                         me.objs.server = webServer;
                         var msg = "start web server on :{protocol}://{domain}:{port}/<appId>/<module>/<action>";
                         msg = msg.format({
                             protocol: me.config.https.enable ? "https" : "http",
                             port: me.config.port,
                             domain: me.config.domain
                         })
                         console.log(msg);
                     }
                     success();
                 });
             } catch (e) {
                 console.log(e);
                 success();
             }
         })

     }
 }

 module.exports = {
     TWebSvr: TWebSvr
 }